﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SimpleGame.Font;
using SimpleGame.Utils;
using Microsoft.Xna.Framework.Input;

namespace SimpleGame.ScreenManagement
{
    public abstract class MenuScreen : GameScreen
    {
        #region Fields

        // Holds all the menu items of a menu screen
        protected List<MenuItem> menuItems = new List<MenuItem>();
        // First menu item is selected
        protected int selectedItem = 0;
        // The title of the menu scren
        protected string menuTitle;

        #endregion

        #region Properties

        /// <summary>
        /// Gets the list of menu items, so menu items can be added or removed.
        /// </summary>
        protected IList<MenuItem> MenuItems
        {
            get { return menuItems; }
        }

        #endregion

        #region Constructor

        public MenuScreen(string menuTitle)
        {
            this.menuTitle = menuTitle;
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Handler for when the user has chosen a menu entry.
        /// </summary>
        protected virtual void OnSelectItem(int menuItemIndex, EventArgs e)
        {
            menuItems[menuItemIndex].OnSelectItem(e);
        }

        /// <summary>
        /// Handler for when the user has canceled the menu.
        /// </summary>
        protected virtual void OnCancel(EventArgs e)
        {
            screenManager.RemoveScreen(this);
        }

        /// <summary>
        /// Helper overload makes it easy to use OnCancel as a MenuEntry event handler.
        /// </summary>
        protected virtual void OnCancel(object sender, EventArgs e)
        {
            OnCancel(e);
        }

        #endregion

        #region Methods

        public void HandleInput()
        {
            // move menu item up?
            if (InputHandler.IsKeyPressed(Keys.Up))
            {
                selectedItem--;
                if (selectedItem < 0)
                {
                    selectedItem = 0;
                }
            }
            // move menu item down?
            if (InputHandler.IsKeyPressed(Keys.Down))
            {
                selectedItem++;
                if (selectedItem >= menuItems.Count)
                {
                    selectedItem = menuItems.Count - 1;
                }
            }
            // was menu item selected?
            if (InputHandler.IsKeyPressed(Keys.Enter))
            {
                OnSelectItem(selectedItem, EventArgs.Empty);
            }
            // was menu canceled?
            if (InputHandler.IsKeyPressed(Keys.Escape))
            {
                OnCancel(null, EventArgs.Empty);
            }
        }

        /// <summary>
        /// Allows the screen the chance to position the menu entries.
        /// </summary>
        protected virtual void UpdateMenuItemPositions()
        {
            Vector2 position = new Vector2(0, 200);

            // update every menu items's position
            for (int i = 0; i < menuItems.Count; i++)
            {
                // center the mneu item horizontally
                position.X = screenManager.GraphicsDevice.Viewport.Width / 2 - menuItems[i].GetWidth(this) / 2;

                // set the menu items position
                menuItems[i].Position = position;

                // move down for the next entry the size of this entry
                position.Y += menuItems[i].GetHeight(this);
            }
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            HandleInput();

            // Update each nested MenuEntry object.
            for (int i = 0; i < menuItems.Count; i++)
            {
                bool isSelected = (i == selectedItem);

                menuItems[i].Update(gameTime, isSelected);
            }


        }

        public override void Draw(GameTime gameTime)
        {
            GraphicsDevice graphics = ScreenManager.SpriteBatch.GraphicsDevice;

            // Clear the graphics device in order to make a (re)draw possible
            // TODO Set backgroundcolor back to black. Currently it's green for the developement phase
            graphics.Clear(Color.Blue);

            // make sure our entries are in the right place before we draw them
            UpdateMenuItemPositions();

            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            // Begin drawing
            spriteBatch.Begin();

            // Draw every menu item
            for (int i = 0; i < menuItems.Count; i++)
            {
                bool isSelected = (i == selectedItem);

                menuItems[i].Draw(gameTime, isSelected);
            }

            // Draw the menu title centered on the screen
            Vector2 titlePosition = new Vector2(graphics.Viewport.Width / 2, 80);
            Vector2 titleTextSize = FontManager.Instance.GetFont("menutitle").SpriteFont.MeasureString(menuTitle);
            Color titleColor = Color.OrangeRed;
            float titleScale = 1.25f;

            FontManager.Instance.DrawString(
                "menutitle",
                menuTitle,
                titlePosition - (titleTextSize / 2),
                titleColor,
                titleScale,
                0f,
                Vector2.Zero);

            // End drawing
            spriteBatch.End();
        }

        #endregion
    }
}
